package code

import common.EnginService
import common.Message
import common.ServerAttributeKey
import io.netty.channel.ChannelHandlerContext
import io.netty.channel.SimpleChannelInboundHandler
import io.netty.handler.timeout.IdleState
import io.netty.handler.timeout.IdleStateEvent
import org.slf4j.LoggerFactory

/**
 * 服务器网络层业务接受handler
 * 由此像业务层派发业务
 * @author King
 */
class ServerChannelHandler : SimpleChannelInboundHandler<Message>() {
    lateinit var service: EnginService

    @Throws(Exception::class)
    override fun channelActive(ctx: ChannelHandlerContext) {
        super.channelActive(ctx)
        service.channelManager.addChannel(ctx.channel())
    }

    @Throws(Exception::class)
    override fun channelRead0(ctx: ChannelHandlerContext, msg: Message) {
        val handler = service.handlerManager.getHandler(msg.getmId(), msg.gethId())
        service.messageDispatch.put(handler,msg)
    }


    @Throws(Exception::class)
    override fun userEventTriggered(ctx: ChannelHandlerContext, evt: Any) {
        if (evt !is IdleStateEvent) {
            return
        }
//2次read空闲超时就断开连接
        if (evt.state() == IdleState.READER_IDLE) {
            val attr = ctx.channel().attr(ServerAttributeKey.netChannel)
            val channel = attr.get()
            if (channel != null) {
                if (!channel.isHeartBeat) {
                    channel.isHeartBeat = true
                    return
                }
            }
            ctx.close()
            //        	losetConnect(ctx);
        }
    }

    @Throws(Exception::class)
    override fun channelInactive(ctx: ChannelHandlerContext) {
        super.channelInactive(ctx)
        losetConnect(ctx)
    }

    /**
     * 丢失连接
     * 模拟玩家退出游戏消息
     * @param ctx
     */
    @Throws(Exception::class)
    private fun losetConnect(ctx: ChannelHandlerContext) {
        service.channelManager.delChannel(ctx.channel())
        val attr = ctx.channel().attr(ServerAttributeKey.netChannel)
        val channel = attr.get()
        if (channel == null || channel.isKick) {
            return
        }
        //抛出掉线消息给业务线程
        val msg = Message.newMessage()
        msg.channel = attr.get()
        msg.setmId(Message.M_ID)
        msg.sethId(Message.H_DISCONNET)
        val handler = service.handlerManager.getHandler(msg.getmId(), msg.gethId())
        service.messageDispatch.put(handler,msg)
    }


    @Throws(Exception::class)
    override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) {
        super.exceptionCaught(ctx, cause)
        ctx.close()
    }

    companion object {
        private val log = LoggerFactory.getLogger(ServerChannelHandler::class.java)
    }

}
